#ifndef PACKET_H
#define PACKET_H

#include <inttypes.h>
#include <stdio.h>

#define STX0 0x5e
#define STX1 0x02
#define STX 0x5e02
#define ETX 0x5e0d
#define ETX0 0x5e
#define ETX1 0x0d
#define RID_HOST 0x00
#define RID_PMS5005 0x01
#define RID_PMB5010 0X08
#define INDEX_STX 0
#define INDEX_RID 2
#define INDEX_RSV 3
#define INDEX_DID 4
#define INDEX_LEN 5
#define INDEX_DAT 6
#define MAX_PACKET_LEN 255+9

typedef struct packet_s{
	uint16_t stx;
	uint8_t rid;
	uint8_t reserved;
	uint8_t did;
	uint8_t length;
	uint8_t *data;
	uint8_t checksum;
	uint16_t etx;
} packet_t;

typedef enum status_e{
	SUCCESS = 0,
	OUT_OF_MEMORY,
	NULL_POINTER,
	SOCKET_FAIL,
	MALFORMED_PACKET,
	WRONG_RID,
	WRONG_CHECKSUM,
	QUEUE_EMPTY,
	WRITE_FAIL,
	READ_FAIL,
	FAIL
} status_t;


typedef enum parse_e {
	PARSE_FULL = 0,
	PARSE_NO_TAIL,
	PARSE_NO_HEAD	
} parse_t;

typedef enum did_e {
	MOT_POS = 0x03,
	MOT_POS_ALL = 0x04,
	MOT_PWM = 0x05,
	MOT_PWM_ALL = 0x06,
	SETUP = 0x07,
	JPEG_PACKET = 0x09,
	PCM_PACKET = 0x0a,
	AUDIO_START_REC = 0x0b,
	AUDIO_STOP_REC = 0x0c,
	AUDIO_START_PLAY = 0x0d,
	AUDIO_STOP_PLAY = 0x0e,
	GPIO = 0x16,
	LCD = 0x17,
	MOT_VEL = 0x1a,
	MOT_VEL_ALL = 0x1b,
	SERVO = 0x1c,
	SERVO_ALL = 0x1d,
	MOT_STATUS = 0x1e,
	TAKE_PICTURE= 0x20,
	ADPCM_RESET = 0x33,
	MOT_FB = 0x7b,
	CUSTOM_AD = 0x7c,
	SENSOR_FB = 0x7d,
	SENSOR_FB_ALL = 0x7f,
	SYSTEM_COM = 0xff,
} did_t;


status_t packet_new(packet_t **packet, 
		uint8_t rid,
		uint8_t reserved, 
		uint8_t did,
		uint8_t length,
		uint8_t *data);
status_t packet_copy(packet_t **new, packet_t *orig);
status_t packet_delete(packet_t *packet);
status_t packet_set_stx(packet_t *packet, uint16_t stx);
status_t packet_set_etx(packet_t *packet, uint16_t etx);
status_t packet_set_rid(packet_t *packet, uint8_t rid);
status_t packet_set_reserved(packet_t *packet, uint8_t reserved);
status_t packet_set_did(packet_t *packet, uint8_t did);
status_t packet_set_data(packet_t *packet, 
			uint8_t length,
			uint8_t *data);
status_t packet_set_checksum(packet_t *packet);
status_t packet_get_stx(packet_t *packet, uint16_t *stx);
status_t packet_get_etx(packet_t *packet, uint16_t *etx);
status_t packet_get_rid(packet_t *packet, uint8_t *rid);
status_t packet_get_reserved(packet_t *packet, uint8_t *reserved);
status_t packet_get_did(packet_t *packet, uint8_t *did);
status_t packet_get_data(packet_t *packet, 
		       uint8_t *length,
		       uint8_t **data);
status_t packet_get_checksum(packet_t *packet, uint8_t *checksum);
status_t packet_serialize(packet_t *packet, uint8_t *stream);
status_t packet_deserialize(packet_t **packet, uint8_t *stream); 
status_t packet_crc_calculate(uint8_t *crc, 
		uint8_t rid, uint8_t res, uint8_t did, uint8_t len,
		uint8_t *data);
status_t packet_are_equal(uint8_t *res, packet_t *packet1, packet_t *packet2);
uint16_t packet_stream_length(uint8_t *stream);
void print_packet_stream(FILE *fstream, uint8_t *ptr);
uint8_t crc_update(uint8_t crc, uint8_t data);
void crc_set(uint8_t *stream);
uint16_t find_packet_stream(uint8_t *ptr, 
				uint16_t offset,
				uint16_t len, 
				uint8_t *dst);
status_t validate_packet_stream(uint8_t *ptr);

#endif
